/*************************************************************************
	> File Name: channel.cpp
	> Author: xuwenlong
	> Mail: myxuan475@126.com 
	> Created Time: 2018年12月04日 星期二 09时26分06秒
 ************************************************************************/
#include "channel.h"
#include <dbms/devices.h>
#include <dbms/transports.h>
#include "acquisition.h"
#include "linkage.h"
#include "collector.h"
#include <transport/transport_manager.h>

#define U8_Bcd(u) ((U8)((u)%10)|((U8)((u)/10))<<4)
#define U32_Offset(u,offset) (((U32)(U8_Bcd(u)))<<(offset))

Channel::Channel(const transmgr_t &trans):
    m_trans(trans),
    m_pTimer(new Timer(getChnName(trans),this)),
    m_bStop(true)
{

}

Channel::~Channel()
{
    StopAcquisitor();
    m_listAcquisitor.clear();
    delete m_pTimer;
}

void Channel::RunTimer()
{
    /* 获取指令 */
    LOG_TRACE();

    time_t acqtime = time(NULL);
    CommitTimer commitTimer(m_pTimer,m_trans.sample);//修改下次时间

    tConnection connector = GetConnector();
    if (!connector.valid()) {
        LOG_ERR("no connector");
        return;
    }

    for (vector<tAcquisitor>::iterator iter = m_listAcquisitor.begin();
         iter != m_listAcquisitor.end();iter++) {
        tAcquisitor acquitor = *iter;
        if (!acquitor.valid())
            continue;
//        BufferDog bufDog;
//#ifndef LOCAL_TEST
        acquitor->DoRun(connector,acqtime);
//#endif
    }
}

bool Channel::clearData()
{
    for (vector<tAcquisitor>::iterator iter = m_listAcquisitor.begin();
         iter != m_listAcquisitor.end();
         iter++) {
        tAcquisitor acquitor = *iter;
        if (acquitor.valid()) {
            acquitor->clearData();
        }
    }
    return true;
}

S32 Channel::commitData(S32 index)
{
    S32 ret = -1;
    for (vector<tAcquisitor>::iterator iter = m_listAcquisitor.begin();
         iter != m_listAcquisitor.end();
         iter++) {
        tAcquisitor acquitor = *iter;
        if (acquitor.valid()) {
            ret = acquitor->commitData(index);
        }
    }
    return ret;
}

bool Channel::IsEqual(const transmgr_t &trans)
{
    return trans == m_trans;
}

void Channel::StartAcquisitor()
{
    initAcquisitor();
    updateConnector(m_trans.sample);
}

void Channel::StopAcquisitor()
{
    m_bStop = true;

    for (vector<tAcquisitor>::iterator iter = m_listAcquisitor.begin();
         iter != m_listAcquisitor.end();
         iter++) {
        tAcquisitor acquitor = *iter;
        if (acquitor.valid()) {
            acquitor->stopAcquire();
        }
    }

    tConnection connector = GetConnector();
    if (connector.valid()) {
        connector->AtomStop();
    }

    m_pTimer->Stop();
    m_listAcquisitor.clear();
}

tAcquisitor Channel::GetAcquisitor(const deviceinfo_t &devinfo)
{
    for (vector<tAcquisitor>::iterator iter = m_listAcquisitor.begin();
         iter != m_listAcquisitor.end();) {
        tAcquisitor acquitor = *iter;
        if (!acquitor.valid())
            iter = m_listAcquisitor.erase(iter);
        else {
            if (acquitor->IsEqualId(devinfo.id))
                return acquitor;
            iter++;
        }
    }
    tAcquisitor tAcquitor;
    tAcquitor = new Collector(devinfo);

    m_listAcquisitor.push_back(tAcquitor);
    return tAcquitor;
}

void Channel::initAcquisitor()
{
    //生成采集器

    devices devs(-1);
    vector<deviceinfo_t> devlist;
    if (m_trans.trans_mode == TM_SEARIAL)
        devlist = devs.getdevices_by_chn(
                    m_trans.trans_addr.portaddr.com);
    else
        devlist = devs.getdevices_by_chn("tcp");

    vector<tAcquisitor>::iterator iter;
    for (iter = m_listAcquisitor.begin();
         iter != m_listAcquisitor.end();) {
        tAcquisitor tAcquitor = *iter;
        bool exist = false;
        if (tAcquitor.valid()) {
            //查找是否存在，存在就更新
            vector<deviceinfo_t>::iterator diter;
            for (diter = devlist.begin();diter != devlist.end();diter++) {
                const deviceinfo_t &dev = *diter;
                if (tAcquitor->IsEqualId(dev.id)) {
                    tAcquitor->updateAcquisitor(dev);
                    tAcquitor->startAcquire();
                    //
                    //如果温控器就同步时间
                    if (dev.dev_type == 5) {
                        struct tm *tm;
                        time_t now = time(NULL);
                        tm = localtime(&now);
                        U32 sync = U32_Offset((tm->tm_wday==0?7:tm->tm_wday),16)|
                                U32_Offset(tm->tm_hour,8)|
                                U32_Offset(tm->tm_min,0);
                        tAcquitor->indicateDevice(
                                    GetConnector(),"ctrl507",sync);
                    }
                    devlist.erase(diter);
                    exist = true;
                    break;
                }
            }
        }

        //存在就继续下一个，不存在就删掉,并继续下一个
        if (!exist) {
            iter = m_listAcquisitor.erase(iter);
        }
        else {
            iter++;
        }
    }

    vector<deviceinfo_t>::iterator diter;
    for (diter = devlist.begin();diter != devlist.end();diter++) {
        const deviceinfo_t &dev = *diter;

        tAcquisitor tAcquitor;
        tAcquitor = new Collector(dev);
        tAcquitor->startAcquire();
        m_listAcquisitor.push_back(tAcquitor);
        if (dev.dev_type == 5) {
            struct tm *tm;
            time_t now = time(NULL);
            tm = localtime(&now);
            U32 sync = U32_Offset((tm->tm_wday==0?7:tm->tm_wday),16)|
                    U32_Offset(tm->tm_hour,8)|
                    U32_Offset(tm->tm_min,0);
            tAcquitor->indicateDevice(
                        GetConnector(),"ctrl507",sync);
        }
    }
}

string Channel::getChnName(const transmgr_t &trans)
{
    if (trans.trans_mode == TM_SEARIAL)
        return trans.trans_addr.portaddr.com;
    else if (trans.trans_mode == TM_TCP)
        return "tcp";
    else
        return "none";
}

tConnection Channel::GetConnector()
{
    DevTransportInterface *devInterface = ((AcquisitionManager*)GetTask(DAS_ACQUISITOR,0))->
            DevInterface();
    if (devInterface)
        return devInterface->GetConnection(m_trans);
    return NULL;
}

vector<tAcquisitor> Channel::GetAllAcquisitors()
{
    return m_listAcquisitor;
}

void Channel::AcquireList(Json::Value &result)
{
    for (vector<tAcquisitor>::iterator iter = m_listAcquisitor.begin();
         iter != m_listAcquisitor.end();
         iter++) {
        tAcquisitor acquitor = *iter;
        if (acquitor.valid()) {
            result.append(acquitor->acquireList());
        }
    }
}

double Channel::dailyMemory()
{
    int total = 0;
    for (vector<tAcquisitor>::iterator iter = m_listAcquisitor.begin();
         iter != m_listAcquisitor.end();
         iter++) {
        tAcquisitor acquitor = *iter;
        if (acquitor.valid()) {
            total += acquitor->acqCount();
        }
    }
    return total*20*(24.0*60/m_trans.sample)/1024.0;
}

BOOL Channel::updateConnector(S32 sample)
{
    time_t diff = time(NULL);//difftime(,0);

    S64 secs = (S64)(60*sample);

    if (secs == 0)
        return FALSE;
    S64 wait = secs-((S64)(diff))%secs;
//    LOG_DEBUG("diff=%lld,secs=%lld,wait=%lld",(S64)diff,secs,wait);

    m_bStop = false;

    if (wait <= 120)
        wait = 1;
    else
        wait -= 120;

    LOG_INFO("time:%s,wait %lld s",
             utils::timetostr(time(NULL)).c_str(),
             wait);
    m_pTimer->Start(wait*1000,kPeriodic);
}


